﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using CrawlerCore;
using HtmlAgilityPack;

namespace WCrawlerLib.WebSession.vBulletin
{
    public class VBulletinForumSession : ForumSessionBase
    {
        #region Properties

        public string SessionHash
        {
            get
            {
                
                foreach (Cookie objCookie in Cookies)
                {
                    if (objCookie.Name.Contains("sessionhash"))
                        return objCookie.Value;
                }
                return "";
            }
        }

        #endregion

        public override string InitEditPostParams(string postParams, params string[] pars)
        {
            ParamDict = new Dictionary<string, string>();
            //subject, message + "\n" + updateReason, postId, HtmlDoc.GetValueInInputTag("hidden", "name", "securitytoken"), updateReason, iconId);
                //=============================================================================
                //EDIT POST PARAMS
                ParamDict.Add("[reason]", pars[4]);
                ParamDict.Add("[title]", pars[0]);
                ParamDict.Add("[message]", pars[1].Replace("&", "%26"));
                //ParamDict.Add("[wysiwyg]", "0");
                ParamDict.Add("[iconid]", string.IsNullOrEmpty(pars[5]) ? "0" : pars[5]);
                ParamDict.Add("[signature]", "1");
                //ParamDict.Add("[parseurl]", HtmlDoc.GetValueInInputTag("hidden", "name", "parseurl"));
                ParamDict.Add("[vbseo_retrtitle]", "1");
                ParamDict.Add("[vbseo_is_retrtitle]", "1");
                //ParamDict.Add("[sbutton]", HtmlDoc.GetValueInInputTag("hidden", "id", "qr_submit"));
                ParamDict.Add("[s]", SessionHash);
                ParamDict.Add("[securitytoken]", pars[3]);
                ParamDict.Add("[do]", "updatepost");
                ParamDict.Add("[p]", pars[2]);
                //ParamDict.Add("[posthash]", GetValueByRegexPattern("posthash\\s\\:\\s\"(?<value>[0-9]+)")); //4x
                //ParamDict.Add("[poststarttime]", GetValueByRegexPattern("poststarttime\\s\\:\\s\"(?<value>[0-9]+)")); //4x
                //ParamDict.Add("[emailupdate]", "9999"); //4x
            InitGeneralPostParams(postParams, pars);
            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override string InitNewReplyParams(string postParams, params string[] pars)
        {
            ParamDict = new Dictionary<string, string>();
            //=============================================================================
                //REPLY POST PARAMS
                ParamDict.Add("[securitytoken]", HtmlDoc.GetValueInInputTag("hidden", "name", "securitytoken"));
                ParamDict.Add("[ajax_lastpost]", HtmlDoc.GetValueByRegexPattern(@"var\sajax_last_post\s\=\s(?<value>[0-9]+)"));
                ParamDict.Add("[message]", pars[0].Replace("&", "%26"));
                //ParamDict.Add("[wysiwyg]", "0");//wysiwyg);
                ParamDict.Add("[fromquickreply]", HtmlDoc.GetValueInInputTag("hidden", "name", "fromquickreply"));
                //ParamDict.Add("[s]", SessionHash);
                ParamDict.Add("[threadid]", HtmlDoc.GetValueInInputTag("hidden", "name", "t"));
                ParamDict.Add("[topicid]", HtmlDoc.GetValueInInputTag("hidden", "name", "p"));
                ParamDict.Add("[specifiedpost]", HtmlDoc.GetValueInInputTag("hidden", "name", "specifiedpost"));
                //ParamDict.Add("[loggedinuser]", HtmlDoc.GetValueInInputTag("hidden", "name", "loggedinuser"));
                //ParamDict.Add("[posthash]", GetValueByRegexPattern("posthash\\s\\:\\s\"(?<value>[0-9]+)"));
                //ParamDict.Add("[poststarttime]", GetValueByRegexPattern("poststarttime\\s\\:\\s\"(?<value>[0-9]+)"));
                //ParamDict.Add("[sbutton]", HtmlDoc.GetValueInInputTag("hidden", "id", "qr_submit"));
                //ParamDict.Add("[parseurl]", HtmlDoc.GetValueInInputTag("hidden", "name", "parseurl"));
                ParamDict.Add("[styleid]", HtmlDoc.GetValueInInputTag("hidden", "name", "styleid")); //3x
            InitGeneralPostParams(postParams, pars);
            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override string InitNewThreadParams(string postParams, params string[] pars)
        {
            ParamDict = new Dictionary<string, string>();
            //"newthread", postParams, subject, message, fId, icon, tagList, prefixId;
                //=============================================================================
                //NEWTHREAD POST PARAMS
                ParamDict.Add("[prefixid]", pars[5]);
                ParamDict.Add("[subject]", pars[0]);
                ParamDict.Add("[message]", pars[1].Replace("&", "%26"));
                //ParamDict.Add("[wysiwyg]", "0");//wysiwyg);
                ParamDict.Add("[taglist]", pars[4]);
                ParamDict.Add("[sendtrackbacks]", "");
                ParamDict.Add("[iconid]", string.IsNullOrEmpty(pars[3]) ? "0" : pars[3]);
                ParamDict.Add("[s]", SessionHash);
                ParamDict.Add("[securitytoken]", HtmlDoc.GetValueInInputTag("hidden", "name", "securitytoken"));
                ParamDict.Add("[f]", pars[2]);
                ParamDict.Add("[do]", "postthread");
                //ParamDict.Add("[posthash]", GetValueByRegexPattern("posthash\\s\\:\\s\"(?<value>[0-9]+)"));
                //ParamDict.Add("[poststarttime]", GetValueByRegexPattern("poststarttime\\s\\:\\s\"(?<value>[0-9]+)"));
                //ParamDict.Add("[loggedinuser]", HtmlDoc.GetValueInInputTag("hidden", "name", "loggedinuser"));
                //ParamDict.Add("[sbutton]", HtmlDoc.GetValueInInputTag("hidden", "id", "qr_submit"));
                //ParamDict.Add("[parseurl]", HtmlDoc.GetValueInInputTag("hidden", "name", "parseurl"));
                ParamDict.Add("[sessionhash]", SessionHash);
                //others
                ParamDict.Add("[vbseo_retrtitle]", "1");
                ParamDict.Add("[vbseo_is_retrtitle]", "1");
                //ParamDict.Add("[emailupdate]", "9999");
                ParamDict.Add("[polloptions]", "4");
            InitGeneralPostParams(postParams, pars);
            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override void InitGeneralPostParams(string postParams, params string[] pars)
        {
            ParamDict = new Dictionary<string, string>();
            //=============================================================================
            //SAME PARAMS
            ParamDict.Add("[wysiwyg]", "0");
            ParamDict.Add("[loggedinuser]", HtmlDoc.GetValueInInputTag("hidden", "name", "loggedinuser"));
            ParamDict.Add("[posthash]", HtmlDoc.GetValueByRegexPattern("posthash\\s\\:\\s\"(?<value>[0-9]+)"));//4x
            if (string.IsNullOrEmpty(ParamDict["[posthash]"]))
                ParamDict["[posthash]"] = HtmlDoc.GetValueInInputTag("hidden", "name", "posthash"); //3x

            ParamDict.Add("[poststarttime]", HtmlDoc.GetValueByRegexPattern("poststarttime\\s\\(:|=)\\s\"(?<value>[0-9]+)")); //4x
            if (string.IsNullOrEmpty(ParamDict["[poststarttime]"]))
                ParamDict["[poststarttime]"] = HtmlDoc.GetValueInInputTag("hidden", "name", "poststarttime"); //3x

            ParamDict.Add("[sbutton]", HtmlDoc.GetValueInInputTag("hidden", "id", "qr_submit"));
            if (string.IsNullOrEmpty(ParamDict["[sbutton]"]))
                ParamDict["[sbutton]"] = HtmlDoc.GetValueInInputTag("submit", "name", "sbutton"); //3x

            ParamDict.Add("[parseurl]", HtmlDoc.GetValueInInputTag("hidden", "name", "parseurl"));
            if (string.IsNullOrEmpty(ParamDict["[parseurl]"]))
                ParamDict["[parseurl]"] = HtmlDoc.GetValueInInputTag("checkbox", "name", "parseurl"); //3x
            
            ParamDict.Add("[emailupdate]", "9999");
            
        }

        
        #region Login

        public override string InitLoginParams(string postParams, params string[] pars)
        {
            ParamDict = new Dictionary<string, string>();
            ParamDict.Add("[vb_login_username]", pars[0]);
            ParamDict.Add("[vb_login_password_hint]", HtmlDoc.GetValueInInputTag("text", "name", "vb_login_password_hint"));
            ParamDict.Add("[vb_login_password]", "");
            ParamDict.Add("[s]", "");
            ParamDict.Add("[cookieuser]", "checked");
            ParamDict.Add("[securitytoken]", "guest");
            ParamDict.Add("[do]", "login");
            ParamDict.Add("[vb_login_md5password]", GetMD5Hash(pars[1]));
            ParamDict.Add("[vb_login_md5password_utf]", GetMD5Hash(pars[1]));
            InitGeneralPostParams(postParams, pars);
            foreach (KeyValuePair<string, string> par in ParamDict)
            {
                if (postParams.Contains(par.Key))
                    postParams = postParams.Replace(par.Key, par.Value);
            }
            return postParams;
        }

        public override bool CheckLoginStatus()
        {
            bool loginStatus = false;
            //if login fail
            if (Response.StatusCode != HttpStatusCode.OK)
                return loginStatus;

            //If count > 1 successfully log in
            if (!string.IsNullOrEmpty(SessionHash))
            {
                loginStatus = true;
            }
            return loginStatus;
        }

        /// <summary>
        /// Get user id
        /// </summary>
        /// <returns></returns>
        public override int GetAccountId()
        {
            int userId = -1;
            //string xPath = ".//a[(contains(@href, '[username]') or contains(.//text(), '[username]')) and contains(@href, 'member')]".Replace("[username]", userName);
            string xPath = ".//a[contains(@href, '[username]') or contains(.//text(), '[username]')]".Replace("[username]", ObjForum.Account.UserName);
            string profileUrl = HtmlDoc.DocumentNode.SelectNodes(xPath)[0].Attributes["href"].Value;
            profileUrl = GeneralClass.GetFullUrl(ObjForum.ForumUrl, profileUrl);
            Regex r = new Regex(@"member\.php\?u=(?<userid>([0-9]+))");
            Match m = r.Match(profileUrl);
            if (m.Success)
                userId = int.Parse(m.Result("${userid}"));
            else
            {
                Get(profileUrl);
                m = r.Match(HtmlDoc.DocumentNode.InnerHtml);
                if (m.Success)
                    userId = int.Parse(m.Result("${userid}"));
            }
            return userId;
        }
        #endregion

        public override void PostNewThread(string subject, string message, string fId, string icon, string tagList, string prefixId)
        {
            //Step1: Get full url new thread and load url
            string newThreadUrl = ObjForum.NewThreadUrlPattern.Replace("[fid]", fId.ToString()).Replace("[sessionhash]", SessionHash);
            newThreadUrl = GeneralClass.GetFullUrl(ObjForum.ForumUrl, newThreadUrl);
            HtmlDocument doc = Get(newThreadUrl);

            //Step2: Find post url in new thread page
            string postNewThreadUrl = "";
            HtmlNodeCollection nodeCollection = doc.DocumentNode.SelectNodes(".//form[@method='post' and contains(@action, 'newthread.php?do=postthread')]");
            if (nodeCollection == null)
                return;
            else
            {
                foreach (HtmlNode node in nodeCollection)
                {
                    if (!string.IsNullOrEmpty(node.OuterHtml))
                    {
                        //string newThreadUrl = node.Attributes["action"].Value;
                        postNewThreadUrl = GeneralClass.GetFullUrl(ObjForum.ForumUrl, node.Attributes["action"].Value);
                    }
                }
            }

            //Step3: Get POST Params 
            _postParams = InitNewThreadParams(ObjForum.NewThreadParams, subject, message, fId, icon, tagList, prefixId);
            //_postParams = InitPostParams(enumPost.NewThread, postParams, subject, message, fId, icon, tagList, prefixId);

            //Step4: Finally start post new thead and return thread num
            Post(postNewThreadUrl);
        }

        public override bool PostNewReply(string topicUrl, string newReplyUrl, string postParams, string message)
        {
            bool result = false;
            //Load topic url
            Get(ObjForum.ForumUrl + "/" + topicUrl);
            //Init post reply url
            string postReplyUrl = ObjForum.ForumUrl + "/" + newReplyUrl.Replace("[threadid]", HtmlDoc.GetValueInInputTag("hidden", "name", "t"));
            //Init post params
            _postParams = InitNewReplyParams(postParams, message);
            //Start post reply
            Post(postReplyUrl);

            if (HtmlWeb.StatusCode == HttpStatusCode.OK)
                result = true;
            return result;
        }

        public override bool PostEdit(string forumUrl, string topicUrl, string postId, string editParams, string subject, string message, string updateReason, string icon)
        {
            throw new NotImplementedException();
        }
    }
}
